package ms.unicorn.modellanguage;

import java.util.HashMap;
import java.util.Map;

import ms.unicorn.Element;
import ms.unicorn.util.ErrorHandler;
import ms.unicorn.util.MLExtensionSchema;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;

public class LanguageRegistry implements MLExtensionSchema {
	private Map<String, IModelLanguage> languages = new HashMap<String, IModelLanguage>();
	
	public static final LanguageRegistry INSTANCE = new LanguageRegistry();
	
	private LanguageRegistry() {
		registerLanguage(new DefaultLanguage());
		loadLanguages();
	}
	
	protected void loadLanguages() {
		IConfigurationElement[] configs = Platform.getExtensionRegistry()
				.getConfigurationElementsFor(EXTENSION_ID);

		for (IConfigurationElement item : configs) {
			if (MODEL_LANGUAGE.equalsIgnoreCase(item.getName())) {
				createModelLanguage(item);
			} 
		}

		registerElementTypes();
	}

	private void createModelLanguage(IConfigurationElement item) {
		try {
			IModelLanguage lang = (IModelLanguage) item
					.createExecutableExtension("handler");
			lang.setId(item.getAttribute("id"));
			lang.setName(item.getAttribute("name"));

			registerLanguage(lang);

			for (IConfigurationElement child : item.getChildren())
				if (child.getName().equalsIgnoreCase("remove")) {
					String targetId = child.getAttribute("targetId");
					removeElement(targetId);
				} else if (child.getName().equalsIgnoreCase("entity")) {
					createLanguageEntity(lang, child);
				} else if (child.getName().equalsIgnoreCase("relation")) {
					createLanguageRelation(lang, child);
				}
		} catch (CoreException e) {
			ErrorHandler.handleException(e);
		}
	}
	
	private void createLanguageEntity(IModelLanguage lang,
			IConfigurationElement child) {
		LanguageEntity e = new LanguageEntity(lang, child);
		lang.addElement(e);
	}

	private void createLanguageRelation(IModelLanguage lang,
			IConfigurationElement child) {
		LanguageRelation e = new LanguageRelation(lang, child);		
		lang.addElement(e);
	}

	public LanguageElement getLanguageElement(Element domainElement) {
		LanguageElement e = null;
		if (domainElement != null) {
			String typeId = domainElement.getElementType();
			for(IModelLanguage lang : languages.values()) {
				e = lang.getElement(typeId);
				if (e != null)
					break;
			}
		}
		return e;
	}

	public void registerLanguage(IModelLanguage language) {
		languages.put(language.getId(), language);
	}
	
	public void removeElement(String elementId) {
		if (languages.containsKey(elementId))
			languages.remove(elementId);
	}

	public IModelLanguage getLanguage(String language) {
		return languages.get(language);
	}

	public void registerElementTypes() {
		for(IModelLanguage lang: languages.values())
			lang.registerElementTypes();
	}
}
